
var string = require('./string.js');
var object = require('./object.js');
var lang = require('./lang.js');

/**
 * 对字符串进行%#&+=以及和\s匹配的所有字符进行url转义
 * @name url.escapeSymbol
 * @function
 * @grammar url.escapeSymbol(source)
 * @param {string} source 需要转义的字符串.
 * @return {string} 转义之后的字符串.
 * @remark
 * 用于get请求转义。在服务器只接受gbk，并且页面是gbk编码时，可以经过本转义后直接发get请求。
 *
 * @return {string} 转义后的字符串
 */
var escapeSymbol = function(source) {

    //TODO: 之前使用\s来匹配任意空白符
    //发现在ie下无法匹配中文全角空格和纵向指标符\v，所以改\s为\f\r\n\t\v以及中文全角空格和英文空格
    //但是由于ie本身不支持纵向指标符\v,故去掉对其的匹配，保证各浏览器下效果一致
    return String(source).replace(/[#%&+=\/\\\ \u3000\f\r\n\t]/g, function(all) {
        return '%' + (0x100 + all.charCodeAt()).toString(16).substring(1).toUpperCase();
    });
};

exports.escapeSymbol = escapeSymbol;


/**
 * 根据参数名从目标URL中获取参数值
 * @name url.getQueryValue
 * @function
 * @grammar url.getQueryValue(url, key)
 * @param {string} url 目标URL
 * @param {string} key 要获取的参数名
 * @meta standard
 * @see url.jsonToQuery
 *
 * @returns {string|null} - 获取的参数值，其中URI编码后的字符不会被解码，获取不到时返回null
 */
var getQueryValue = function (url, key) {
    var reg = new RegExp(
                        "(^|&|\\?|#)"
                        + string.escapeReg(key)
                        + "=([^&#]*)(&|\x24|#)",
                    "");
    var match = url.match(reg);
    if (match) {
        return match[2];
    }

    return null;
};

exports.getQueryValue = getQueryValue;



/**
 * 将json对象解析成query字符串
 * @name url.jsonToQuery
 * @function
 * @grammar url.jsonToQuery(json[, replacer])
 * @param {Object} json 需要解析的json对象
 * @param {Function=} replacer_opt 对值进行特殊处理的函数，function (value, key)
 * @see url.queryToJson,url.getQueryValue
 *
 * @return {string} - 解析结果字符串，其中值将被URI编码，{a:'&1 '} ==> "a=%261%20"。
 */
var jsonToQuery = function (json, replacer_opt) {
    var result = [],
        itemLen,
        replacer = replacer_opt || function (value) {
          return escapeSymbol(value);
        };

    object.each(json, function(item, key){
        // 这里只考虑item为数组、字符串、数字类型，不考虑嵌套的object
        if (lang.isArray(item)) {
            itemLen = item.length;
            // value的值需要encodeURIComponent转义吗？
            // FIXED 优化了escapeSymbol函数
            while (itemLen--) {
                result.push(key + '=' + replacer(item[itemLen], key));
            }
        } else {
            result.push(key + '=' + replacer(item, key));
        }
    });

    return result.join('&');
};

exports.jsonToQuery = jsonToQuery;

/**
 * 解析目标URL中的参数成json对象
 * @name url.queryToJson
 * @function
 * @grammar url.queryToJson(url)
 * @param {string} url 目标URL
 * @see url.jsonToQuery
 *
 * @returns {Object} - 解析为结果对象，其中URI编码后的字符不会被解码，'a=%20' ==> {a:'%20'}。
 */
var queryToJson = function (url) {
    var query   = url.substr(url.lastIndexOf('?') + 1),
        params  = query.split('&'),
        len     = params.length,
        result  = {},
        i       = 0,
        key, value, item, param;

    for (; i < len; i++) {
        if(!params[i]){
            continue;
        }
        param   = params[i].split('=');
        key     = param[0];
        value   = param[1];

        item = result[key];
        if ('undefined' == typeof item) {
            result[key] = value;
        } else if (lang.isArray(item)) {
            item.push(value);
        } else { // 这里只可能是string了
            result[key] = [item, value];
        }
    }

    return result;
};

exports.queryToJson = queryToJson;

